#ifndef SERVER_H
#define SERVER_H

#include "../GlobalClass.h"
#include "IOCPDllClass/IOCP_Pleafles.h"

#include <QUuid>
#include <QWidget>
//#include <QThreadPool>
#include <QQueue>
//#include <QWaitCondition>
//#include <windows.h>

/*
 * 鹰:和IOCP配合实现的C/S模型,包含了 加解密(Code控制),控制字符,包长度(粘包处理),群 等
 *
 * 流程:
 * 1.IOCP新建SocketContext,回调Fn_IOCP_SetSocketExtraData_Callback,新建一个_ClientInfo保存到IOCP的SocketExtraData中.
 * 2.IOCP接受Accept到新Socket后,先回调Fn_IOCP_Init_SocketExtraData_Callback,再进行Accept回调.
 * 3.发送数据时的Socket校验:
 *   由于使用池,所有的信息和数据不会释放,所以可以使用指针_ClientInfo进行传递和操作.
 *   若没有使用池,则发送时只能使用_SocketInfo::_SocketContext结构体进行传递和操作.
*/

class _ClientInfo;
class _ClientsGroupInfo;
class IOCP_Pleafles;


// 设置两个创建和释放SocketExtraData的回调函数(池!)
typedef void* (FUNCTION_CALL_TYPE *_SetGroupExtraDataCallback)();
typedef void (FUNCTION_CALL_TYPE *_UnsetGroupExtraDataCallback)(void *pGroupExtraData);
typedef void (FUNCTION_CALL_TYPE *_InitGroupExtraDataCallback)(void *pGroupExtraData);
typedef void (FUNCTION_CALL_TYPE *_ReleaseGroupExtraDataCallback)(void *pGroupExtraData);

//一个 群 数据
class _ClientsGroupInfo
{
    //Q_FLAGS(_GroupStatusFlags)
public:
    //房间状态
    enum _GroupStatusFlag
    {
        Status_Normal = 0, //正常,(可加入)
        Status_Locked = 1  //锁,(不可加入)
    };
    Q_DECLARE_FLAGS(_GroupStatusFlags, _GroupStatusFlag)        //写在和E1同命名空间下(或同一类中)

    //房间基础数据
    struct _GroupInfo
    {
        int nClientsMaxCount;  //最多玩家数
        QString strPassword;   //密码
    };

public:
    explicit _ClientsGroupInfo(IOCP_Pleafles *iocp = nullptr) :
        m_pIOCP(iocp)
    {
        m_uuid = QUuid::createUuid();
        if(SetGroupExtraDataCallback == nullptr)
            m_pClientsGroupExtraData = nullptr;
        else
            m_pClientsGroupExtraData = SetGroupExtraDataCallback();


        m_flagStatus = Status_Normal;
        m_GroupInfo.nClientsMaxCount = 0;
        m_nMaster = -1;

        //_pool_init();
    }
    virtual ~_ClientsGroupInfo()
    {
        if(UnsetGroupExtraDataCallback != nullptr)
            UnsetGroupExtraDataCallback(m_pClientsGroupExtraData);

        //_pool_release();
    }

//池需要调用的函数
    virtual void _pool_init()
    {
        if(InitGroupExtraDataCallback != nullptr)
            InitGroupExtraDataCallback(this->m_pClientsGroupExtraData);
    }
    virtual void _pool_release()
    {
        m_flagStatus = Status_Normal;
        m_GroupInfo.nClientsMaxCount = 0;
        m_nMaster = -1;

        if(ReleaseGroupExtraDataCallback != nullptr)
            ReleaseGroupExtraDataCallback(this->m_pClientsGroupExtraData);
    }

public:
    //发送 数据 给 组里 其他 所有客户,除了pClientInfo
    int SendToGroupAllClients(QByteArray ba, _ClientInfo *pClientInfo = nullptr);

public:
    IOCP_Pleafles       *m_pIOCP;     //IOCP指针,用到Send函数

public:
    _GroupStatusFlags   m_flagStatus;
    _GroupInfo          m_GroupInfo;

    QUuid               m_uuid;          //房间ID(唯一性)
    QList<_ClientInfo*> m_listClients;   //客户列表
    //QList<QSharedPointer<_ClientInfo>> m_listClients;

    int                 m_nMaster;        //房主,目前无用

    //群的其他数据指针
    void                *m_pClientsGroupExtraData;

    //群的池操作,回调函数
    static _SetGroupExtraDataCallback SetGroupExtraDataCallback;
    static _UnsetGroupExtraDataCallback UnsetGroupExtraDataCallback;
    static _InitGroupExtraDataCallback InitGroupExtraDataCallback;
    static _ReleaseGroupExtraDataCallback ReleaseGroupExtraDataCallback;
};

/*
//每个SocketInfo
struct _SocketInfo {
    QList<_SocketInfo*>::Iterator pos;   //链表中的地址
    void *pSocket;
    void *pData;    //用户数据
};*/

//服务端 的 客户数据,二次封装(加入群,状态,控制字符,数据包扩展,在线统计等)
class _ClientInfo : public _SocketInfo
{
public:
    explicit _ClientInfo() :
        m_ucInControlByte(0),
        m_nStep(0),
        //transfersCode(-1),
        m_pGroup(nullptr)
    {
        m_pClientExtraData = nullptr;    //这个也作为 池数据
        //_pool_init();
    }
    virtual ~_ClientInfo()
    {
        //if(m_pClientExtraData != nullptr)
        //    delete m_pClientExtraData;

        m_pClientExtraData = nullptr;
        //_pool_release();
    }

    //池节点初始化(然后保存到队列中供调用)
    //如果要 记录开始时间 ,则不能写在这里!
    virtual void _pool_init() Q_DECL_OVERRIDE
    {
        _SocketInfo::_pool_init();


        m_dtLogin = QDateTime::currentDateTime();
        m_bDisconnected = false;
        //qDebug() << "[Server]Server _ClientInfo _pool_init";
    }

    //池节点释放(然后保存到队列中供调用)
    //如果要 记录结束时间 ,则不能写在这里!
    virtual void _pool_release() Q_DECL_OVERRIDE
    {
        m_listInCodeData.clear();
        m_listInTransfersCode.clear();  //接受加密包时的code

        m_ucInControlByte = 0;
        m_nStep = 0;
        m_pGroup = nullptr;

        m_nClientType = 0;
        m_dtLogout = QDateTime::currentDateTime();
        m_bDisconnected = true;
        //qDebug() << "[Server]Server _ClientInfo _pool_release";


        _SocketInfo::_pool_release();
    }


public:


public:
    //unsigned long ulRecivedSize;    //已接受包的长度(不含数据)

    quint8              m_ucInControlByte;               //数据包的控制字符
    int                 m_nStep;                           //网络包识别时的 第几阶段

    QList<QByteArray>   m_listInCodeData;   //要加密的包队列
    QList<qint16>       m_listInTransfersCode;  //接受加密包时的code


    _ClientsGroupInfo   *m_pGroup;        //加入的房间

    //_ClientStatus clientStatus;

    //是否断线
    bool                m_bDisconnected;
    qint16              m_nClientType;          //客户端类型
    QDateTime           m_dtLogin;              //登录时间
    QDateTime           m_dtLogout;             //登出时间

    //额外的数据(由用户去定义,创建,删除)
    void                *m_pClientExtraData;    //这个也作为 池数据,所以不能再_release中置nullptr!!
};




//二次封装,加入日志,群,配置,将IOCP功能扩展(重写回调函数和信号)
class Server : public QObject
{
    Q_OBJECT

public:
    explicit Server(QObject *parent = nullptr);
    virtual ~Server();

//IOCP的4个线程发送的5个信号(可在使用前绑定Debug函数)
signals:
    void s_Debug(QString msg);
    void s_Critical(QString msg);

    void s_Accept(_SocketInfo::_SocketContext socketContext);
    void s_Disconnect(int type, _SocketInfo::_SocketContext socketContext);
    void s_ReadyRead(QByteArray baData, quint8 controlByte, _SocketInfo::_SocketContext socketContext);


//群函数,只是操作,并不向玩家发送数据,没有重载,可单独调用!!
public:
    //找到房间,没有返回nullptr
    _ClientsGroupInfo* GetGroup(QUuid id);

    //创建一个房间
    _ClientsGroupInfo* CreateGroup(int playerMaxCount = 2, QString password = "");

    //加入pGroup房间,如果为nullptr则随机加入
    //0为成功,<0各种错误:-1已经加入群组;-2所有房间满;-3房间状态不对;-4指针空
    int JoinGroup(_ClientInfo* pClientInfo, _ClientsGroupInfo *pGroup, const QString& password = "");
    //加入房间id;-10无这个房间
    int JoinGroup(_ClientInfo* pClientInfo, QUuid id, const QString& password = "");

    //pClientInfo退出房间,不解散群
    //ret>=0群剩余客户,<0出错
    //!!!如果用户是群主,解散群,或者换群主
    int ExitGroup(_ClientInfo* pClientInfo);

    //关闭房间,处理房间内玩家数据
    //返回0正常,<0出错
    int CloseGroup(_ClientsGroupInfo *pGroup);


    //给sock发送所有房间的信息
    //bool SendAllGroupsInfoToClient(_ClientInfo* pClientInfo);

    //给所有玩家发送 sockGroup的id和玩家数的更新信息
    //bool SendAllGroupsInfoToAllClients(SocketGroup* sockGroup, int type);

public://!!!
    void sendGroupInfoToAllClients(_ClientsGroupInfo *pGroup){} //给所有Clients发送pGroup信息(新建)
    void sendGroupInfoToAllClients(QUuid uuid, int type){}  //同上,type:1:关闭
    void sendClientJoinInfoToAllClients(_ClientInfo *pClientData){} //给所有Clients发送pClientData的Join信息

    void sendClientReadyInfoToAllClients(_ClientInfo *pClientData){} //给所有Clients发送pClientData的Ready状态
    void sendToAllClientInGroup(QByteArray ba, _ClientInfo *pClientData){}   //给Group中其他Client发送ba




//其他(外部调用):
    //显示信息
    /*
    virtual void Message(QString msg)
    {
        //qDebug()<<"ThreadId:"<<::GetCurrentThreadId();
        qDebug() << msg;
    }
    //调试信息,写入日志
    virtual void Debug(QString msg)
    {
        //qDebug()<<"ThreadId:"<<::GetCurrentThreadId();
        / *if(m_fileLog.isOpen())
        {
            m_fileLogStream << msg << "\r\n";
            m_fileLog.flush();
        }* /
        qDebug() << msg;
    }
    virtual void Critical(QString msg)
    {
        qCritical() << msg;
    }*/



    virtual bool OpenLog(QString filename = "ServerLog.txt")
    {
        m_fileLog.setFileName(filename);
        return m_fileLog.open(QIODevice::Append | QIODevice::Text);
    }
    virtual void CloseLog()
    {
        m_fileLog.close();
    }



    //创建1个Code并发送(0~10000)
    bool createTransmitsCodeAndSend(_ClientInfo *pClientInfo, int count = 1)
    {
        while(count > 0)
        {
            pClientInfo->m_listInTransfersCode << (qrand() % 10000);  //保存
            count --;
        }

        QByteArray ba = m_IOCPModel.newSendData(0x8c);
        QDataStream ds(&ba,QIODevice::ReadWrite);
        ds.device()->seek(ba.size());
        ds << pClientInfo->m_listInTransfersCode;
        m_IOCPModel.CorrectDataLength(ba);
        m_IOCPModel.send(pClientInfo, ba);
        qDebug() << "[Server]发送加密Code:" << pClientInfo->m_listInTransfersCode;
        return true;
    }

    //将baData使用baCode解密!
    //返回true为解密成功
    bool recieveUseTransfersCode(_ClientInfo *pClientInfo, QByteArray &baData, QByteArray baCode = QByteArray())
    {

        //可以直接解密
        if(!baCode.isEmpty())   // && m_listOutTransfersCode.count() > 0)
        {
            //如果队列中有数据,拿出第一个数据
            if(!pClientInfo->m_listInCodeData.isEmpty())
            {
                if(!baData.isEmpty())
                    pClientInfo->m_listInCodeData.append(baData);
                baData = pClientInfo->m_listInCodeData.takeFirst();
            }

            //showHex(ba.data(),ba.length());
            if(!baData.isEmpty())
            {
                //解密,使用循环异或
                int i;
                for(i = 0; i < baData.length(); i++)
                    baData[i] = baData.at(i) ^ baCode.at(i % baCode.length());

                qDebug() << "[Server]解密完成";
                return true;


                //showHex(ba.data(),ba.length());
                //outTransfersCode = -1;
                //m_listOutTransfersCode.takeFirst();
            }
            else
            {
                qWarning() << "[!Server]WARNING:无数据解密!";
                return false;
            }
        }
        else
        {
            qDebug() << "[Server]Data加入队列,等待解密Code";
            if(!baData.isEmpty())
                pClientInfo->m_listInCodeData.append(baData);
        }

        return false;

    }

public:
    bool Start()
    {
        m_nAcceptedCount = 0;
        if(OpenLog() == false)
            return false;
        return m_IOCPModel.Start();
    }

    void Stop()
    {
        m_IOCPModel.Stop();
        CloseLog();
        m_poolClientsGroupInfo.clearEmptyList();
        m_poolClientsGroupInfo.clearUsingList();
        m_mapGroups.clear();
    }

/*
    int Start()
    {
    //IOCP服务启动
        m_IOCPModel.init();

        m_IOCPModel.SetIOCPMessageCallback((void*)Fn_IOCP_Message_Callback,this);
        m_IOCPModel.SetIOCPDbgMessageCallback((void*)Fn_IOCP_MessageDbg_Callback,this);
        m_IOCPModel.SetIOCPAcceptCallback((void*)Fn_IOCP_Accept_Callback,this);
        m_IOCPModel.SetIOCPRecvCallback((void*)Fn_IOCP_Recv_Callback,this);
        m_IOCPModel.SetIOCPCloseCallback((void*)Fn_IOCP_Close_Callback,this);

        m_IOCPModel.SetServerIP("0.0.0.0");
        m_IOCPModel.SetServerPort(8806);

        m_IOCPModel.Start();

    //数据库连接
        db = QSqlDatabase::addDatabase("QMYSQL","mysql");
        db.setHostName("leamus.gotoftp2.com");
        db.setDatabaseName("leamus");
        db.setUserName("leamus");
        db.setPassword("19880723");
        if(!db.open())
        {
            Debug(QString("Database Connection ERROR:%1").arg(db.lastError().text()));
        }
        else
        {
            Debug(QString("Database Connection Successful"));
        }
        return 0;
    }
    void Stop()
    {
        m_IOCPModel.Stop();
        if(db.isValid() && db.isOpen())
            db.close();
    }
*/


//数据成员
public:
    IOCP_Pleafles           m_IOCPModel;      //IOCP模型对象
    quint32                 m_nRecievedDataMaxSize;  //一个包最大的数据长度,大于时长度非法(为0不限制)
    quint32                 m_nDataCacheMaxSize;   //最大 接受数据缓存的个数(超过会释放无用数据)
    quint32                 m_nAcceptedCount;       //统计总共连接次数

    //所有 群组 表
    QMap<QUuid,_ClientsGroupInfo*> m_mapGroups;

    _LMS_Pool<_ClientsGroupInfo> m_poolClientsGroupInfo;    //Group的池
    //QThreadPool m_ThreadPool;


    Config                  m_ConfigFile;    //配置文件
    QVariantMap             m_vmapConfig;
    //QSqlDatabase db;


//私有数据成员
protected:

    QFile                   m_fileLog;         //日志
    QTextStream             m_txtstreamLog;    //日志


//IOCP回调函数
public:
    //注意:这些都是线程回调函数,不可以直接操作主线程UI!!!
    //将列表操作放入主线程,就不需要锁了
    static void FUNCTION_CALL_TYPE Fn_IOCP_Message_Callback(const char *msg,void *param)
    {
        QString str = QString("%1【%2】").arg(QString::fromLocal8Bit(msg))
                .arg(QDateTime::currentDateTime().toString(Qt::SystemLocaleDate));

        qDebug() << "[Server]Message:" << str;
        emit ((Server*)param)->s_Debug(str);
        //((Server*)param)->Debug(QString::fromLocal8Bit(msg));
        //((Server*)param)->m_IOCPModel.Release(msg);
    }

    static void FUNCTION_CALL_TYPE Fn_IOCP_MessageDbg_Callback(const char *msg,void *param)
    {
        QString str = QString("%1【%2】").arg(QString::fromLocal8Bit(msg))
                .arg(QDateTime::currentDateTime().toString(Qt::SystemLocaleDate));

        qDebug() << "[Server]MessageDbg:" << str;
        emit ((Server*)param)->s_Critical(str);
        //((Server*)param)->Debug(QString::fromLocal8Bit(msg));
        //((Server*)param)->m_IOCPModel.Release(msg);
    }

    //Accept的池 实现
    static void FUNCTION_CALL_TYPE Fn_IOCP_Accept_Callback(int socketID,void *pIOCPSocketContext,void *param)
    {
        _ClientInfo *pClientInfo = (_ClientInfo*)((Server*)param)->m_IOCPModel.SocketExtraData(pIOCPSocketContext);
        //pClientInfo->_pool_init();

        pClientInfo->m_SocketContext.nSocketID = socketID;
        pClientInfo->m_SocketContext.pIOCPSocketContext = pIOCPSocketContext;
        pClientInfo->m_SocketContext.pSocketInfo = pClientInfo;

        qDebug() << "[Server]Accept:New Client Coming:" << socketID << pIOCPSocketContext << pClientInfo;

        emit ((Server*)param)->s_Accept(pClientInfo->m_SocketContext);

        ((Server*)param)->m_nAcceptedCount ++;
    }

    //Accept的 非池 实现
    static void FUNCTION_CALL_TYPE Fn_IOCP_Accept_Callback_Non_Pool(int socketID,void *pIOCPSocketContext,void *param)
    {
        //((Server*)param)->mapClientSocket.insert(socket, new _ClientInfo);

        //鹰:尽量快速的设置SetSocketExtraData,这样Recv和Disconnect时才能保证SocketExtraData得到正确值
        _ClientInfo* pClientInfo = new _ClientInfo;
        ((Server*)param)->m_IOCPModel.SetSocketExtraData(pClientInfo, pIOCPSocketContext);

        pClientInfo->m_SocketContext.nSocketID = socketID;
        pClientInfo->m_SocketContext.pIOCPSocketContext = pIOCPSocketContext;
        pClientInfo->m_SocketContext.pSocketInfo = pClientInfo;

        qDebug() << "[Server]Accept:New Client Coming:" << socketID << pIOCPSocketContext << pClientInfo;

        emit ((Server*)param)->s_Accept(pClientInfo->m_SocketContext);

        ((Server*)param)->m_nAcceptedCount ++;

        /*  //要放在主线程里(线程不安全)

        ((Server*)param)->m_AllClientsList.append(pClientInfo);
        emit ((Server*)param)->s_Debug(QString("Accept:%1").arg((int)pIOCPSocketContext));
        */
    }

    static void FUNCTION_CALL_TYPE Fn_IOCP_Close_Callback(int type, void *pIOCPSocketContext, void *param)
    {
        qDebug() << "[Server]CloseSocket回调:" << type;
        //提前解析出来,防止被IOCP删除
        _ClientInfo *pClientInfo = (_ClientInfo*)((Server*)param)->m_IOCPModel.SocketExtraData(pIOCPSocketContext);
        pClientInfo->m_bDisconnected = true;

        //!!!在主线程中删除pClientInfo,因为还有善后处理
        emit ((Server*)param)->s_Disconnect(type, pClientInfo->m_SocketContext);


        /*  //要放在主线程里(线程不安全)
        ((Server*)param)->m_AllClientsList.removeOne(pClientInfo);
        delete pClientInfo;
        //delete ((Server*)param)->mapClientSocket.take(socket);

        emit ((Server*)param)->s_Debug(QString("[Server]CloseSocket(%1):%2").arg(type).arg((int)pIOCPSocketContext));
        */
    }

    static void FUNCTION_CALL_TYPE Fn_IOCP_Recv_Callback(void*buf,unsigned long buflen,void *pIOCPSocketContext,void*param)
    {
        //((Server*)param)->m_IOCPModel.Send(socket,(char*)buf,buflen);
        //showHex((char*)buf,buflen);

        _ClientInfo *pClientInfo = (_ClientInfo*)((Server*)param)->m_IOCPModel.SocketExtraData(pIOCPSocketContext);

        qDebug() << "[Server]Recv:" << pIOCPSocketContext << pClientInfo << "recived:" << buflen<<(char*)buf;

        pClientInfo->m_baIn.append((char*)buf, buflen);
        //char *pPacketStart = (char*)buf;
        //unsigned long ulReaded = 0;           //已经用过的(相当于指针)

        //循环处理粘包,缺包部分(鹰:目前实现的是包足够了才发送,还有一种是 大于最大值也发送 没做.)
        while(1)
        {
            //qDebug() << pClientInfo->m_dsIn.device()->bytesAvailable()
            //         << pClientInfo->m_dsIn.device()->pos();

            //pClientInfo->m_dsIn.device()->peek(pClientInfo->m_dsIn.device()->bytesAvailable());

            int packageHeaderFlagLength = ((Server*)param)->m_IOCPModel.m_baPackageHeaderFlag.length();

            //读取标志字符
            if(pClientInfo->m_nStep == 0)
            {
                if(pClientInfo->m_dsIn.device()->bytesAvailable() >= packageHeaderFlagLength)
                {
                    //找到 头标志
                    int index = pClientInfo->m_baIn.indexOf(((Server*)param)->m_IOCPModel.m_baPackageHeaderFlag,pClientInfo->m_dsIn.device()->pos());
                    if(index >= 0)
                    {
                        pClientInfo->m_dsIn.skipRawData(index - pClientInfo->m_dsIn.device()->pos() + packageHeaderFlagLength);  //释放无用的
                        pClientInfo->m_nStep = 1;
                        qDebug() << "[Server]SocketRecieved 标志串:" << index << index + packageHeaderFlagLength;
                    }
                    else
                    {
                        qDebug() << "[Server]SocketRecieved:数据中找不到标志,继续等待接收";

                        //!!!如果缓存数大于 m_nDataCacheMaxSize,则释放掉无用的数据(最多留下 packageHeaderFlagLength - 1 个)
                        if(pClientInfo->m_dsIn.device()->bytesAvailable() > ((Server*)param)->m_nDataCacheMaxSize)
                        {
                            int n = pClientInfo->m_dsIn.device()->bytesAvailable() - (packageHeaderFlagLength - 1);
                            pClientInfo->m_dsIn.skipRawData(n);
                            qDebug() << "[Server]SocketRecieved:释放无用数据:" << n << "个字节";
                        }
                        break;
                    }
                }
                else break;
            }

            //读取控制字符
            //if (inBlockSize == 0 && bytesAvailable() >= sizeof(quint32))
            if(pClientInfo->m_nStep == 1)
            {
                if(pClientInfo->m_dsIn.device()->bytesAvailable() >= sizeof(quint8))
                {
                    pClientInfo->m_dsIn >> pClientInfo->m_ucInControlByte;
                    pClientInfo->m_nStep = 2;
                    qDebug() << "[Server]SocketRecieved:控制字符:" << pClientInfo->m_ucInControlByte;
                }
                else break;

            }

            //读长度部分
            //if(pClientInfo->m_ulDataSize == 0 && pClientInfo->m_dsIn.device()->bytesAvailable() >= sizeof(unsigned long)) //没有读取过头部(长度)
            if(pClientInfo->m_nStep == 2)
            {
                if(pClientInfo->m_dsIn.device()->bytesAvailable() >= sizeof(unsigned long))
                {
                    //保存剩下的长度
                    quint32 t;
                    pClientInfo->m_dsIn >> t;
                    if(((Server*)param)->m_nRecievedDataMaxSize > 0 && t > ((Server*)param)->m_nRecievedDataMaxSize)
                    {
                        pClientInfo->m_nStep = 0;
                        qWarning()<<"[!Server]SocketRecieved WARNING:数据长度非法:" << t;
                    }
                    else
                    {
                        pClientInfo->m_ulDataSize = t;    //读数据长度
                        pClientInfo->m_nStep = 3;
                        qDebug() << "[Server]SocketRecieved:数据长度:" << pClientInfo->m_ulDataSize;
                    }


                    if(pClientInfo->m_ulDataSize == 0)
                    {
                        //pClientInfo->m_nStep = 0;    //数据长度为0,则返回第0步
                    }
                }
                else break;
            }

            //读数据部分
            //if(pClientInfo->m_ulDataSize != 0 && pClientInfo->m_dsIn.device()->bytesAvailable() >= pClientInfo->m_ulDataSize)
            if(pClientInfo->m_nStep == 3)
            {
                if(pClientInfo->m_dsIn.device()->bytesAvailable() >= pClientInfo->m_ulDataSize)
                {
                    //qDebug()<<pClientInfo->m_dsIn.device()->bytesAvailable();

                    qDebug() << "[Server]SocketRecieved:数据读取完毕";


                    //存一个完整数据到baData
                    QByteArray baData(pClientInfo->m_ulDataSize, Qt::Uninitialized);
                    pClientInfo->m_dsIn.readRawData(baData.data(), pClientInfo->m_ulDataSize);

                    pClientInfo->m_nStep = 0;
                    pClientInfo->m_ulDataSize = 0;

                    //数据处理
                    switch(pClientInfo->m_ucInControlByte)
                    {
                    case (quint8)0x8b:   //发送n个Code
                        //((Server*)param)->createTransmitsCodeAndSend(pClientInfo, 20);
                        break;
                    case (quint8)0x8c:   //接受到个Code
                        //in >> outTransfersCode;
                        break;
                    case (quint8)0x8d:
                        qDebug() << "[Server]接受到加密数据";
                        emit ((Server*)param)->s_ReadyRead(baData, pClientInfo->m_ucInControlByte, pClientInfo->m_SocketContext);

                        break;
                    //case 0x4d:
                    //    break;
                    default:
                        emit ((Server*)param)->s_ReadyRead(baData, pClientInfo->m_ucInControlByte, pClientInfo->m_SocketContext);
                        break;
                    }


                    /*
                    int id;
                    pClientInfo->m_dsIn >> id;
                    emit ((Server*)param)->s_Debug(QString("包ID:%d").arg(id));
                    */


                    //qDebug() << "3m_dsInfo:"
                    //         << pClientInfo->m_dsIn.device()->bytesAvailable()
                    //         << pClientInfo->m_dsIn.device()->pos();
                }
                else break;
            }
        }

        //释放掉已经用了的数据
        pClientInfo->m_baIn.remove(0,pClientInfo->m_dsIn.device()->pos());
        pClientInfo->m_dsIn.device()->reset();

        //emit ((Server*)param)->mapClientSocket.value(socket)->pGroup;
    }

    static void FUNCTION_CALL_TYPE Fn_IOCP_Send_Callback(void*buf, unsigned long buflen, unsigned long bufTransfered, void *pIOCPSocketContext, void*param)
    {
        qDebug() << "[Server]Send回调:" << bufTransfered<<"/" << buflen << (char*)buf;

        //_ClientInfo *pClientInfo = (_ClientInfo*)((Server*)param)->m_IOCPModel.SocketExtraData(pIOCPSocketContext);

        //QString str = QString("[Server]Send回调:%1/%2").arg(bufTransfered).arg(buflen);
        //emit ((Server*)param)->s_Debug(str);

        return;
        /*
        if(bufTransfered == 0)
        {
            qDebug()<<"[Server]貌似断开连接?";
            return;
        }
        else if(bufTransfered > buflen)
        {
            qDebug()<<"[Server]发送过多?";
            return;
        }
        else if (bufTransfered < buflen)
        {
            qDebug()<<"[Server]继续发送!...";
            ((Server*)param)->m_IOCPModel.Send(pIOCPSocketContext, (char*)buf + bufTransfered, buflen - bufTransfered);
            return;
        }
        else
        {
            qDebug()<<"[Server]发送成功";
            return;
        }*/
    }





//4个SocketExtraData回调(IOCP回调)
    static void* FUNCTION_CALL_TYPE Fn_IOCP_SetSocketExtraData_Callback()
    {
        qDebug() << "[Server]Fn_IOCP_SetSocketExtraData_Callback";
        return new _ClientInfo;
    }

    static void FUNCTION_CALL_TYPE Fn_IOCP_UnsetSocketExtraData_Callback(void *pExtraData)
    {
        if(pExtraData != nullptr)
        {
            qDebug() << "[Server]Fn_IOCP_UnsetSocketExtraData_Callback";
            delete (_ClientInfo*)pExtraData;
        }
        else
            qCritical() << "[!Server]UnsetSocketExtraData Callback ERROR!";
    }

    static void FUNCTION_CALL_TYPE Fn_IOCP_Init_SocketExtraData_Callback(void *pExtraData)
    {
        if(pExtraData != nullptr)
        {
            qDebug() << "[Server]Fn_IOCP_Init_SocketExtraData_Callback";
            ((_ClientInfo*)pExtraData)->_pool_init();
        }
        else
            qCritical() << "[!Server]InitSocketExtraData Callback ERROR!";
    }

    static void FUNCTION_CALL_TYPE Fn_IOCP_Release_SocketExtraData_Callback(void *pExtraData)
    {
        if(pExtraData != nullptr)
        {
            qDebug() << "[Server]Fn_IOCP_Release_SocketExtraData_Callback";
            ((_ClientInfo*)pExtraData)->_pool_release();
        }
        else
            qCritical() << "[!Server]ReleaseSocketExtraData Callback ERROR!";
    }
};

Q_DECLARE_OPERATORS_FOR_FLAGS(_ClientsGroupInfo::_GroupStatusFlags)  //写在全局

#endif // SERVER_H
